#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>

#define TRUE 1
#define FALSE 0
#define HUGE 1000000

#include "pthreadpool.h"
int i = 0;

#define container_of0(ptr, type, member) ({            \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
                (type *)( (char *)__mptr - offsetof(type,member) );})

#define container_of(ptr, type, member) (            \
                (type *)( (char *)ptr - offsetof(type,member) ) )

typedef enum {
	undefID = 0,
	Last1m,
	Last2m,
	Last3m,
	Last5m,
	Last10,
	ParamCnt
} funParam;

int randi(int max)
{
	int rand_num;
	static struct random_data rand_data;
	static char rand_state[256];
	static bool initialized = FALSE;

	if (!initialized) {
		initstate_r(time(0), rand_state, sizeof(rand_state), &rand_data);
		initialized = TRUE;
	}
	random_r(&rand_data, &rand_num);
	double cof = rand_num / (RAND_MAX + 1.0);
	return (int)(max * cof);
}

void print1(void *a)
{
	int j;
	for (j = 0; j < randi(HUGE); j++)
		randi(1000);
	printf("%s func 1 pid %ld\n", (char *)a, pthread_self());
	free((char *)a);
	return;
}

void print2(void *a)
{
	int j;
	for (j = 0; j < randi(HUGE); j++)
		randi(5000);
	printf("%s func 2 pid %ld\n", (char *)a, pthread_self());
	free((char *)a);
	return;
}

void print3(void *a)
{
	int j;
	for (j = 0; j < randi(HUGE); j++)
		randi(10000);
	printf("%s func 3 pid %ld\n", (char *)a, pthread_self());
	free((char *)a);
	return;
}

void null_op(void *a)
{
	printf("running a null function :) \n");
	free((char *)a);
	return;
}

#define asizeof(a)     (int)(sizeof (a) / sizeof ((a)[0]))

typedef void (*v_func_t) (void *);
void *(*compfunc) (const void *v1, const void *v2);

typedef struct XFUNCS {

	int v_funcId;
	int stkid;
	long time;
	funParam fpm;

} XFUNC_Node;

XFUNC_Node sNode[] = {
	{0, 0, 0, undefID},
	{1, 0, 0, undefID},
	{2, 0, 0, undefID},
	{3, 0, 0, undefID}
};

v_func_t *Xprint;

v_func_t getFunc(XFUNC_Node * sn, int x)
{
	if (x < asizeof(sNode))
		return Xprint[sn[x].v_funcId];
	else
		return Xprint[sn[x].v_funcId];
}

int main(int argc,char **argv)
{

	int j, x;
	v_func_t xprint[] = { &print1, &print2, &print3, NULL };
	funParam fx;
	struct pthreadpool_t *tpool = malloc(sizeof(*tpool));
	tpool_init(tpool, 50, 100);

	XFUNC_Node *sn;

	Xprint = calloc(asizeof(sNode) + 1, sizeof(v_func_t));
	Xprint[0] = &print1;
	Xprint[1] = &print2;
	Xprint[2] = &print3;
	Xprint[3] = &null_op;

	sn = calloc(100, sizeof(sNode));

	printf("sNode %d xprint %d\n", asizeof(sNode), asizeof(xprint));
	for (j = 0; j < 100; j++) {
		sn[j].v_funcId = randi(asizeof(xprint));
	}

	j = 0;

	while (1) {
		char *s = calloc(128, sizeof(char));
		x = randi(HUGE) % asizeof(xprint);
		j++;
		sprintf(s, "%d called randi %d", j, x);
		tpool->tasklist.task_add(&tpool->tasklist, getFunc(sn, x), s);
	}									  //tpool->tpool_wait(tpool);

	free(sn);
	//free(tpool);

}
